import type { Root } from 'mdast';
import type { Plugin } from 'unified';
import { visit } from 'unist-util-visit';

/**
 * A remark plugin to render unknown directives-- denoted by a colon (:), as a text node type
 * Valid directive names are keys included in the JSX.IntrinsicElements type
 *
 * Example of conversion:
 * ```md
 * :invalid-directive[some text] --> some text
 * I am:an unintentional directive --> I am:an unintentional directive
 * ```
 **/

/**
 * Accepted directive names are keys included in type JSX.IntrinsicElements
 * See type Components from 'react-markdown/lib/index.d.ts'
 */
enum MarkdownDirectives {
  a,
  abbr,
  address,
  area,
  article,
  aside,
  audio,
  b,
  base,
  bdi,
  bdo,
  big,
  blockquote,
  body,
  br,
  button,
  canvas,
  caption,
  center,
  cite,
  code,
  col,
  colgroup,
  data,
  datalist,
  dd,
  del,
  details,
  dfn,
  dialog,
  div,
  dl,
  dt,
  em,
  embed,
  fieldset,
  figcaption,
  figure,
  footer,
  form,
  h1,
  h2,
  h3,
  h4,
  h5,
  h6,
  head,
  header,
  hgroup,
  hr,
  html,
  i,
  iframe,
  img,
  input,
  ins,
  kbd,
  keygen,
  label,
  legend,
  li,
  link,
  main,
  map,
  mark,
  menu,
  menuitem,
  meta,
  meter,
  nav,
  noindex,
  noscript,
  object,
  ol,
  optgroup,
  option,
  output,
  p,
  param,
  picture,
  pre,
  progress,
  q,
  rp,
  rt,
  ruby,
  s,
  samp,
  search,
  slot,
  script,
  section,
  select,
  small,
  source,
  span,
  strong,
  style,
  sub,
  summary,
  sup,
  table,
  template,
  tbody,
  td,
  textarea,
  tfoot,
  th,
  thead,
  time,
  title,
  tr,
  track,
  u,
  ul,
  'var',
  video,
  wbr,
  webview,
  svg,
  animate,
  animateMotion,
  animateTransform,
  circle,
  clipPath,
  defs,
  desc,
  ellipse,
  feBlend,
  feColorMatrix,
  feComponentTransfer,
  feComposite,
  feConvolveMatrix,
  feDiffuseLighting,
  feDisplacementMap,
  feDistantLight,
  feDropShadow,
  feFlood,
  feFuncA,
  feFuncB,
  feFuncG,
  feFuncR,
  feGaussianBlur,
  feImage,
  feMerge,
  feMergeNode,
  feMorphology,
  feOffset,
  fePointLight,
  feSpecularLighting,
  feSpotLight,
  feTile,
  feTurbulence,
  filter,
  foreignObject,
  g,
  image,
  line,
  linearGradient,
  marker,
  mask,
  metadata,
  mpath,
  path,
  pattern,
  polygon,
  polyline,
  radialGradient,
  rect,
  stop,
  switch,
  symbol,
  text,
  textPath,
  tspan,
  use,
  view,
}

export const renderRemarkUnknowns: Plugin<void[], Root> = () => {
  return (tree) => {
    visit(tree, (node: any) => {
      if (node.type !== 'textDirective') return;

      const isKnownDirective = !!MarkdownDirectives[node.name];
      if (isKnownDirective) return;

      node.type = 'text';
      node.value = `:${node.name}`;
    });
  };
};
